#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;

{{#usesXml}}
use serde_xml_rs;
{{/usesXml}}
use serde::ser::Serializer;

{{#usesXml}}
use std::collections::{HashMap, BTreeMap};
{{/usesXml}}
{{^usesXml}}
use std::collections::HashMap;
{{/usesXml}}
use models;
use swagger;
use std::string::ParseError;
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}

{{#models}}{{#model}}
{{#description}}/// {{{description}}}
{{/description}}{{#isEnum}}/// Enumeration of values.
/// Since this enum's variants do not hold data, we can easily define them them as `#[repr(C)]`
/// which helps with FFI.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))]{{#xmlName}}
#[serde(rename = "{{{xmlName}}}")]{{/xmlName}}
pub enum {{{classname}}} { {{#allowableValues}}{{#enumVars}}
    #[serde(rename = {{{value}}})]
    {{{name}}},{{/enumVars}}{{/allowableValues}}
}

impl ::std::fmt::Display for {{{classname}}} {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self { {{#allowableValues}}{{#enumVars}}
            {{{classname}}}::{{{name}}} => write!(f, "{}", {{{value}}}),{{/enumVars}}{{/allowableValues}}
        }
    }
}

impl ::std::str::FromStr for {{{classname}}} {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
{{#allowableValues}}{{#enumVars}}            {{{value}}} => Ok({{{classname}}}::{{{name}}}),
{{/enumVars}}{{/allowableValues}}            _ => Err(()),
        }
    }
}
{{/isEnum}}
{{^isEnum}}
{{#dataType}}
{{#isMapModel}}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
{{/isMapModel}}
{{^isMapModel}}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
{{/isMapModel}}
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
{{#xmlName}}
#[serde(rename = "{{{xmlName}}}")]
{{/xmlName}}
pub struct {{{classname}}}({{{dataType}}});

impl ::std::convert::From<{{{dataType}}}> for {{{classname}}} {
    fn from(x: {{{dataType}}}) -> Self {
        {{{classname}}}(x)
    }
}

{{#vendorExtensions.x-is-string}}
impl std::str::FromStr for {{{classname}}} {
    type Err = ParseError;
    fn from_str(x: &str) -> Result<Self, Self::Err> {
        Ok({{{classname}}}(x.to_string()))
    }
}
{{/vendorExtensions.x-is-string}}

impl ::std::convert::From<{{{classname}}}> for {{{dataType}}} {
    fn from(x: {{{classname}}}) -> Self {
        x.0
    }
}

impl ::std::ops::Deref for {{{classname}}} {
    type Target = {{{dataType}}};
    fn deref(&self) -> &{{{dataType}}} {
        &self.0
    }
}

impl ::std::ops::DerefMut for {{{classname}}} {
    fn deref_mut(&mut self) -> &mut {{{dataType}}} {
        &mut self.0
    }
}

{{/dataType}}{{^dataType}}{{#arrayModelType}}{{#vendorExtensions}}{{#itemXmlName}}// Utility function for wrapping list elements when serializing xml
#[allow(non_snake_case)]
fn wrap_in_{{{itemXmlName}}}<S>(item: &Vec<{{{arrayModelType}}}>, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serde_xml_rs::wrap_primitives(item, serializer, "{{{itemXmlName}}}")
}

{{/itemXmlName}}{{/vendorExtensions}}{{! vec}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]
pub struct {{{classname}}}({{#vendorExtensions}}{{#itemXmlName}}#[serde(serialize_with = "wrap_in_{{{itemXmlName}}}")]{{/itemXmlName}}{{/vendorExtensions}}Vec<{{{arrayModelType}}}>);

impl ::std::convert::From<Vec<{{{arrayModelType}}}>> for {{{classname}}} {
    fn from(x: Vec<{{{arrayModelType}}}>) -> Self {
        {{{classname}}}(x)
    }
}

impl ::std::convert::From<{{{classname}}}> for Vec<{{{arrayModelType}}}> {
    fn from(x: {{{classname}}}) -> Self {
        x.0
    }
}

impl ::std::iter::FromIterator<{{{arrayModelType}}}> for {{{classname}}} {
    fn from_iter<U: IntoIterator<Item={{{arrayModelType}}}>>(u: U) -> Self {
        {{{classname}}}(Vec::<{{{arrayModelType}}}>::from_iter(u))
    }
}

impl ::std::iter::IntoIterator for {{{classname}}} {
    type Item = {{{arrayModelType}}};
    type IntoIter = ::std::vec::IntoIter<{{{arrayModelType}}}>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<'a> ::std::iter::IntoIterator for &'a {{{classname}}} {
    type Item = &'a {{{arrayModelType}}};
    type IntoIter = ::std::slice::Iter<'a, {{{arrayModelType}}}>;

    fn into_iter(self) -> Self::IntoIter {
        (&self.0).into_iter()
    }
}

impl<'a> ::std::iter::IntoIterator for &'a mut {{{classname}}} {
    type Item = &'a mut {{{arrayModelType}}};
    type IntoIter = ::std::slice::IterMut<'a, {{{arrayModelType}}}>;

    fn into_iter(self) -> Self::IntoIter {
        (&mut self.0).into_iter()
    }
}

impl ::std::ops::Deref for {{{classname}}} {
    type Target = Vec<{{{arrayModelType}}}>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ::std::ops::DerefMut for {{{classname}}} {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "conversion", derive(LabelledGeneric))]{{#xmlName}}
#[serde(rename = "{{{xmlName}}}")]{{/xmlName}}
pub struct {{{classname}}} {
{{#vars}}{{#description}}    /// {{{description}}}
{{/description}}{{#isEnum}}    // Note: inline enums are not fully supported by openapi-generator
{{/isEnum}}    #[serde(rename = "{{{baseName}}}")]{{#vendorExtensions}}{{#itemXmlName}}
    #[serde(serialize_with = "wrap_in_{{{itemXmlName}}}")]{{/itemXmlName}}{{/vendorExtensions}}{{#required}}
    pub {{{name}}}: {{#isNullable}}swagger::Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}},
{{/required}}{{^required}}{{#isNullable}}
    #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")]
    #[serde(default = "swagger::nullable_format::default_optional_nullable")]{{/isNullable}}
    #[serde(skip_serializing_if="Option::is_none")]
    pub {{{name}}}: Option<{{#isNullable}}swagger::Nullable<{{/isNullable}}{{#isListContainer}}Vec<{{#items}}{{{dataType}}}{{/items}}>{{/isListContainer}}{{^isListContainer}}{{{dataType}}}{{/isListContainer}}{{#isNullable}}>{{/isNullable}}>,
{{/required}}

{{/vars}}
}

impl {{{classname}}} {
    pub fn new({{#vars}}{{^defaultValue}}{{{name}}}: {{#isNullable}}swagger::Nullable<{{/isNullable}}{{{dataType}}}{{#isNullable}}>{{/isNullable}}, {{/defaultValue}}{{/vars}}) -> {{{classname}}} {
        {{{classname}}} {
{{#vars}}            {{{name}}}: {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{{name}}}{{/defaultValue}},
{{/vars}}
        }
    }
}
{{/arrayModelType}}
{{/dataType}}
{{/isEnum}}

{{#usesXml}}
{{#usesXmlNamespaces}}
{{#xmlNamespace}}
impl {{{classname}}} {
    /// Associated constant for this model's XML namespace.
    #[allow(dead_code)]
    pub const NAMESPACE: &'static str = "{{{xmlNamespace}}}";
}

{{/xmlNamespace}}
{{/usesXmlNamespaces}}
impl {{{classname}}} {
    /// Helper function to allow us to convert this model to an XML string.
    /// Will panic if serialisation fails.
    #[allow(dead_code)]
    pub(crate) fn to_xml(&self) -> String {
        {{#xmlNamespace}}
        let mut namespaces = BTreeMap::new();
        // An empty string is used to indicate a global namespace in xmltree.
        namespaces.insert("".to_string(), Self::NAMESPACE.to_string());
        serde_xml_rs::to_string_with_namespaces(&self, namespaces).expect("impossible to fail to serialize")
        {{/xmlNamespace}}
        {{^xmlNamespace}}
        serde_xml_rs::to_string(&self).expect("impossible to fail to serialize")
        {{/xmlNamespace}}
    }
}
{{/usesXml}}
{{/model}}
{{/models}}
